﻿namespace Sai.Core.Introspection
{
	using System;
	using System.Collections.Generic;
    using System.Text;

	public class Signature : IExactlyMatch<Signature>, ILooselyMatch<Signature>, ISourceCodeProvider
	{
		public Signature()
		{
			this.FormalParameters = new ParameterCollection();
		}

		public Signature(string methodName)
			: this()
		{
			this.Name = methodName;
		}

		public Signature(string methodName, IList<Parameter> formalParameters)
		{
			this.Name = methodName;
			this.FormalParameters = new ParameterCollection(formalParameters);
		}

		public int ParameterCount
		{
			get
			{
				return this.FormalParameters.Count;
			}
		}

		private string Name { get; set; }

		private ParameterCollection FormalParameters { get; set; }

		public void Add(Parameter formalParameter)
		{
			this.FormalParameters.Add(formalParameter);
		}

		public override string ToString()
		{
            StringBuilder builder = new StringBuilder();

            builder.Append(this.Name);
            builder.Append(" (");

            for (int i = 0; i < this.FormalParameters.Count; ++i)
            {
                Parameter p = this.FormalParameters[i];

                builder.Append(p.TypeName);

                if (i < this.FormalParameters.Count - 1)
                {
                    builder.Append(",");
                }
            }

            builder.Append(")");

            return builder.ToString();
		}

		public bool ExactMatchFor(Signature other)
		{
			bool exact = string.Compare(
				this.ToString(),
				other.ToString(),
				StringComparison.Ordinal) == 0;

			return exact;
		}

        public bool LooseMatchFor(Signature other)
        {
            return this.FormalParameters.Count == other.FormalParameters.Count;
        }

		public SourceCode ToCode()
		{
            SourceCode code = new SourceCode();

            for (int i = 0; i < this.FormalParameters.Count; ++i)
            {
                Parameter p = this.FormalParameters[i];

                code.Add(p.ToCode());

                if (i < this.FormalParameters.Count - 1)
                {
                    code.Add(new PunctuationTag(","));
                }
            }

            return code;
		}
    }
}
